package com.xu.ReenterLock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @author xudenghui
 * @create 2023-03-03 10:24
 **/
public class CompareTest {


    private class MyReentrantLock extends AbstractQueuedSynchronizer{
        @Override
        protected boolean tryAcquire(int arg) {
            final Thread current = Thread.currentThread();
            while (true){
                int c = getState();
                if (c==0){
                    if (compareAndSetState(0, arg)){
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
            }
        }

        @Override
        protected  boolean tryRelease(int arg) {
            int c = getState()-arg;
            if (Thread.currentThread() != getExclusiveOwnerThread()){
                throw new IllegalMonitorStateException();
            }
            boolean free = false;
            if (c == 0){
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }
    }


    public static void main(String[] args) throws InterruptedException {
        CompareTest test = new CompareTest();
        test.test1();
        test.test2();
    }


    public void test1() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        long begin = System.currentTimeMillis();
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 2; i++) {
            service.submit(()->{
                for (int j = 0; j < 500000000; j++) {
                    reentrantLock.lock();
                    doBusiness();
                    reentrantLock.unlock();
                }
            });
        }
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
        System.out.println("ReentrantLock cost:"+(System.currentTimeMillis()-begin));
    }


    public void test2() throws InterruptedException {
        MyReentrantLock  reentrantLock = new MyReentrantLock ();
        long begin = System.currentTimeMillis();
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 2; i++) {
            service.submit(()->{
                for (int j = 0; j < 500000000; j++) {
                    reentrantLock.tryAcquire(1);
                    doBusiness();
                    reentrantLock.tryRelease(1);
                }
            });
        }
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
        System.out.println("ReentrantLock cost:"+(System.currentTimeMillis()-begin));
    }

    private static void doBusiness() {
        // 空实现，模拟程序快速运行
    }
}
